﻿using System;
using System.Collections.Generic;
using Crevice2D.WPFEditorHost;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;

namespace Patyk.MapEditor.Geometry
{
    public class Vertex : Polygon
    {
        static public int id = 0;

        public Vector2 Position;
        public int ID;

        private Vector2 _w1 = new Vector2(10, 0);
        private Vector2 _w2 = new Vector2(0, 10);

        public FiredEvent OnMouseClicked;

        public Vertex(Vector2 vektor)
            : base(null)
        {
            Position = vektor;
            ID = id;
            id++;
            Lines.Add(new Line(Position - _w1 - _w2, Position + _w1 - _w2));
            Lines.Add(new Line(Position + _w1 - _w2, Position + _w1 + _w2));
            Lines.Add(new Line(Position + _w1 + _w2, Position - _w1 + _w2));
            Lines.Add(new Line(Position - _w1 + _w2, Position - _w1 - _w2));
        }

        public string _ID
        {
            get { return ID.ToString(); }
        }

        public override void Update()
        {
 	         base.Update();

             //if (moueOver && Editor._this._currentMouseState.LeftButton == ButtonState.Pressed &&
             //    Editor._this._previousMouseState.LeftButton == ButtonState.Released)
             //{
             //    // If someone has subscribed to this event, tell them it has fired.
             //    if (OnMouseClicked != null)
             //        OnMouseClicked(this);
             //}
        }
    }

    public class Polygon 
    {
        public List<Line> Lines { get; set; }

        // Delegate definition of an event.
        public delegate void FiredEvent(object sender);

        // Instances of delegate event.
        public FiredEvent OnMouseOver;
        public FiredEvent OnMouseOut;

        public Color Color = Color.Red;
        protected bool moueOver = false;

        public Polygon(List<Vector2> nodes)
        {
            Lines = new List<Line>();
            if (nodes != null)
            {
                for (int i = 0; i < nodes.Count; ++i)
                {
                    Lines.Add(new Line(nodes[i], nodes[(i + 1) % 4]));
                }
            }
        }

        public IEnumerator<Line> GetEnumerator()
        {
            Line[] items = Lines.ToArray();

            foreach (Line item in items)
            {
                yield return item;
            }
        }

        public virtual void Update()
        {
            // Check for mouse over and moust out.
            if (UsefulTrigonometry.PointInPolygon(Editor.MousePos, this))
            {
                moueOver = true;

                // If someone has subscribed to this event, tell them it has fired.
                if (OnMouseOver != null)
                    OnMouseOver(this);
            }
            else
            {
                if (moueOver)
                {
                    moueOver = false;
                    // If someone has subscribed to this event, tell them it has fired.
                    if (OnMouseOut != null)
                        OnMouseOut(this);
                }
            }
        }
    }

    public class Line   
    {
        public Vector2 Start;
        public Vector2 End;

        public Line(Vector2 start, Vector2 end)
        {
            Start = start;
            End = end;
        }
    }

    static public class UsefulTrigonometry
    {
        /// <summary>
        /// Point in polygon check.
        /// </summary>
        /// <param name="point">The point.</param>
        /// <param name="polygon">The polygon.</param>
        /// <returns>True if point is inside, false otherwise.</returns>
        static public bool PointInPolygon(Point point, Polygon polygon) {

               bool inside = false;

               foreach (var side in polygon.Lines) 
               {
                    if (point.Y > Math.Min(side.Start.Y, side.End.Y))
                        if (point.Y <= Math.Max(side.Start.Y, side.End.Y))
                            if (point.X <= Math.Max(side.Start.X, side.End.X))
                            {
                                float xIntersection = side.Start.X + ((point.Y - side.Start.Y) / (side.End.Y - side.Start.Y)) * (side.End.X - side.Start.X);
                                if (point.X <= xIntersection)
                                    inside = !inside;
                            }
               }
               return inside;
        }

        static public Vector2 IntersectionPoint(Line l1, Line l2)
        {
            float x1 = l1.Start.X;
            float y1 = l1.Start.Y;
            float x2 = l1.End.X;
            float y2 = l1.End.Y;
            float x3 = l2.Start.X;
            float y3 = l2.Start.Y;
            float x4 = l2.End.X;
            float y4 = l2.End.Y;

            float Ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1));
            float Ub = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1));

            float x = x1 + Ua * (x2 - x1);
            float y = y1 + Ub * (y2 - y1);

            return new Vector2(x, y);
        }
    }
}
